package ca.nfb.media.nfbPlayer.net
{
	import ca.nfb.media.nfbPlayer.ComModule;
	import ca.nfb.media.nfbPlayer.NFBPyroBrew;
	import ca.nfb.media.nfbPlayer.views.NFBPlayerView;
	import ca.turbulent.media.Pyro;
	import ca.turbulent.media.events.ErrorEvent;
	import ca.turbulent.media.events.PyroEvent;
	import ca.turbulent.media.events.StatusUpdateEvent;
	
	import flash.events.Event;
	import flash.events.FullScreenEvent;
	import flash.external.ExternalInterface;
	import flash.system.Capabilities;
	
	public class Tracker extends NFBPlayerView
	{	
		
		public static const TRACKABLE_REACHED_PERCENT_POINT	:String = "reachedPercentPoint";
		public static const TRACKABLE_REACHED_TIME_POINT	:String = "reachedTimePoint";
		public static const TRACKABLE_BUFFERED_PERCENT_POINT:String = "bufferedPercentPoint";
		public static const TRACKABLE_EVENT					:String = "trackableEvent";
		
		public static var DEFAULT_TRACKABLES				:Array = 	[{type:Tracker.TRACKABLE_EVENT, value:PyroEvent.COMPLETED},
																			{type:Tracker.TRACKABLE_EVENT, value:PyroEvent.NEW_STREAM_INIT},
																			{type:Tracker.TRACKABLE_EVENT, value:ErrorEvent.FILE_NOT_FOUND_ERROR},
																			{type:Tracker.TRACKABLE_REACHED_PERCENT_POINT, value:1},
																			{type:Tracker.TRACKABLE_REACHED_PERCENT_POINT, value:25},
																			{type:Tracker.TRACKABLE_REACHED_PERCENT_POINT, value:50},
																			{type:Tracker.TRACKABLE_REACHED_PERCENT_POINT, value:75},
																			{type:Tracker.TRACKABLE_REACHED_PERCENT_POINT, value:95},
																			{type:Tracker.TRACKABLE_BUFFERED_PERCENT_POINT, value:50},
																			{type:Tracker.TRACKABLE_BUFFERED_PERCENT_POINT, value:100}
																		];
		
		private var progressIndex						:Number = 0;
		private var checkFrequency						:Number = 10;
		
		private var percentPointsReached				:Object = new Object();
		private var percentPRArray						:Array = new Array();
		private var percentPRIndex						:int = 0;
		
		private var timePointsReached					:Object = new Object();
		private var timePRArray							:Array = new Array(); 
		private var timePRIndex							:int = 0;
		
		private var percentPointsBuffered				:Object = new Object();
		private var percentPBArray						:Array = new Array();
		private var percentPBIndex						:int = 0;

		private var trackableEvents						:Object = new Object();
		private var trackableEventsArray				:Array = new Array();
		private var trackableEventIndex					:int = 0;
		
		private var preventStreamStartDuplicate			:Boolean = true;
		public var trappedLastCall						:String = "";
		
		public function Tracker()
		{
			super();	
			var defaults:Array = Tracker.DEFAULT_TRACKABLES;
			initializeTracker(defaults);
		}
		
		private function initializeTracker(trackables:Array):void
		{
			player.registerProgressCallback({name:this.name, funct:onProgress});
			
			if (trackables.length > 0)
				addTrackables(trackables);
			
			if (player.hasEventListener(PyroEvent.NEW_STREAM_INIT))
				player.removeEventListener(PyroEvent.NEW_STREAM_INIT, checkSAEvents);
				
			player.addEventListener(PyroEvent.NEW_STREAM_INIT, checkSAEvents, false, 0, true);
			
			if (player.hasEventListener(ErrorEvent.CONNECTION_ERROR))
				player.removeEventListener(ErrorEvent.CONNECTION_ERROR, checkSAEvents);
				
			player.addEventListener(ErrorEvent.CONNECTION_ERROR, checkSAEvents, false, 0, true);
			
			if (player.hasEventListener(ErrorEvent.FILE_NOT_FOUND_ERROR))
				player.removeEventListener(ErrorEvent.FILE_NOT_FOUND_ERROR, checkSAEvents);
				
			player.addEventListener(ErrorEvent.FILE_NOT_FOUND_ERROR, checkSAEvents, false, 0, true);
			
			if (core.trackPageURL)
				this.trackPageURL();
				
			if (core.trackPageRefferer)
				this.trackReferrerURL();
		}
		
		
		
		public function addReachedPercentPoint(val:Number):void
		{
			var percent:Number = Math.floor(val);
			percentPointsReached[String(percent)] = {tracked:false, index:percentPRIndex, value:percent};
			percentPRArray.push(percentPointsReached[String(percent)]);
			percentPRIndex++;
		}
		
		public function addReachedTimePoint(val:Number):void
		{	
			var time:Number = Math.floor(val);
			timePointsReached[String(time)] = {tracked:false, index:timePRIndex, value:time};
			timePRArray.push(timePointsReached[String(time)]);
			timePRIndex++;
		}
		
		public function addBufferedPercentPoint(val:Number):void
		{
			var percent:Number = Math.floor(val);
			percentPointsBuffered[String(percent)] = {tracked:false, index:percentPBIndex, value:percent};
			percentPBArray.push(percentPointsBuffered[String(percent)]);
			percentPBIndex++;
		}
	
		
		public function addTrackableEvent(evtName:String):void
		{
			trackableEvents[evtName] = {tracked:false, index:trackableEventIndex, value:evtName};
			trackableEventsArray.push(trackableEvents[evtName]);
			trackableEventIndex++;
		}
		
		public function addTrackables(arr:Array):void
		{
			for (var i:Number=0; i<arr.length; ++i)
			{
				switch (arr[i]['type'])
				{
					case Tracker.TRACKABLE_REACHED_PERCENT_POINT:
					addReachedPercentPoint(arr[i]['value']);
					break;
					
					case Tracker.TRACKABLE_REACHED_TIME_POINT:
					addReachedTimePoint(arr[i]['value']);
					break;
					
					case Tracker.TRACKABLE_BUFFERED_PERCENT_POINT:
					addBufferedPercentPoint(arr[i]['value']);
					break;
					
					case Tracker.TRACKABLE_EVENT:
					addTrackableEvent(arr[i]['value']);
					break;
				
				}
			}
		}
		
		private function checkSAEvents(evt:Event):void
		{
			checkTrackableEvent(evt.type);
		}
		
		
		private function checkTrackableEvent(evtName:String):void
		{
			if (trackableEvents[String(evtName)])
			{
				trackableEvents[String(evtName)].tracked = true;
				ComModule.getInstance().setStats(String(trackableEvents[String(evtName)].value));
				trappedLastCall = String(trackableEvents[String(evtName)].value);
				//ComModule.getInstance().core.outputConsole.appendHTMLText("eventTracked="+trackableEvents[String(evtName)].value);
			}
		}
		
		
		public function onProgress():void
		{
			if (this.progressIndex >= this.checkFrequency)
			{
				if (percentPRArray.length > 0)
				{
					var percentPoint:Number = Math.floor(player.progressRatio * 100);
					if (percentPointsReached[String(percentPoint)] != null && !percentPointsReached[String(percentPoint)].tracked)
					{
						percentPointsReached[String(percentPoint)].tracked = true;
						ComModule.getInstance().setStats("percentPoint reached :"+String(percentPointsReached[String(percentPoint)].value));
						trappedLastCall = String("percentPoint reached :"+String(percentPointsReached[String(percentPoint)].value));
						//ComModule.getInstance().core.outputConsole.appendHTMLText("reachedPercentPoint="+percentPointsReached[String(percentPoint)].value);
					}	
				}
						
				if (timePRArray.length > 0)
				{
					var timePoint:Number = Math.floor(player.time+player.timeOffset);
					if (timePointsReached[String(timePoint)] != null && !timePointsReached[String(timePoint)].tracked)
					{
						timePointsReached[String(timePoint)].tracked = true;
						ComModule.getInstance().setStats("timePoint reached :"+String(timePointsReached[String(timePoint)].value));
						trappedLastCall = String("timePoint reached :"+String(timePointsReached[String(timePoint)].value));
						//ComModule.getInstance().core.outputConsole.appendHTMLText("reachedTimePoint="+timePointsReached[String(timePoint)].value);
					}	
				}
					
				if (percentPBArray.length > 0)
				{
					var bufferedPercent:Number = Math.floor(player.loadRatio*100);
					if (percentPointsBuffered[String(bufferedPercent)] != null && !percentPointsBuffered[String(bufferedPercent)].tracked)
					{
						percentPointsBuffered[String(bufferedPercent)].tracked = true;
						ComModule.getInstance().setStats("bufferedPercent reached :"+String(percentPointsBuffered[String(bufferedPercent)].value));
						trappedLastCall = String("bufferedPercent reached :"+String(percentPointsBuffered[String(bufferedPercent)].value));
						//ComModule.getInstance().core.outputConsole.appendHTMLText("bufferedPercentPoint="+percentPointsBuffered[String(bufferedPercent)].value);
					}
				}
				
				this.progressIndex = 0;
			}
			else
			{
				this.progressIndex++;
			}	
		}	
		
		public static function overrideDefaultTrackables(trackables:Array):void
		{
			Tracker.DEFAULT_TRACKABLES = trackables;
		}
		
		
		private function resetTrackingTables():void
		{
			for (var a:* in percentPointsReached)  percentPointsReached[a]['tracked'] = false;
			for (var b:* in timePointsReached)  timePointsReached[b]['tracked'] = false;
			for (var c:* in percentPointsBuffered)  percentPointsBuffered[c]['tracked'] = false;
			for (var d:* in trackableEvents)  trackableEvents[d]['tracked'] = false;
		}
		
		public function trackPageURL():void
		{
			var urlPath:String;
			if (core.pageURL)
				urlPath = core.pageURL;
			else
				urlPath = ExternalInterface.call("window.location.href.toString");
					
			ComModule.getInstance().setStats("URLTracking :pageURL="+urlPath);
			trappedLastCall = "URLTracking :pageURL="+urlPath;
		}
		
		public function trackReferrerURL():void
		{
			var referrerURL:String;
			if (core.reffererURL)
				referrerURL = core.reffererURL;
			else
				referrerURL = ExternalInterface.call("top.document.referrer");
				
			ComModule.getInstance().setStats("URLTracking :referrerURL="+referrerURL);
			trappedLastCall = "URLTracking :referrerURL="+referrerURL;
		}
		
		public function trackPlayerVersion():void
		{
			ComModule.getInstance().setStats("infos: flashPlayerVersion="+Capabilities.version);
			trappedLastCall = "infos :flashPlayerVersion="+Capabilities.version;
		}
		
		public function trackScreenResolution():void
		{
			ComModule.getInstance().setStats("infos :screenResolution="+String(Capabilities.screenResolutionX)+
						","+String(Capabilities.screenResolutionY)+", dpi="+String(Capabilities.screenDPI));
			
			trappedLastCall = "infos :screenResolution="+String(Capabilities.screenResolutionX)+","+
						String(Capabilities.screenResolutionY)+", dpi="+String(Capabilities.screenDPI);
		}
		
		public function trackErrorTimeLength(type:String):void
		{
			ComModule.getInstance().setStats("Error :timeVSdurationError="+type);
		}
		
		
		public function sendBugReport(troubleID:String):void
		{
			ComModule.getInstance().setStats("bugReport :troubleInfo="+troubleID + ", version="+Capabilities.version+
				", serverString="+Capabilities.serverString+" ,fileURL="+ComModule.getInstance().latestFileURL+" ,time="+player.formattedTime+" ,streamQuality="+
				player.streamQuality+" ,connectionSpeed="+player.connectionSpeed);
			
			trappedLastCall = "bugReport :troubleInfo="+troubleID + ", version="+Capabilities.version+
				", serverString="+Capabilities.serverString+" ,fileURL="+ComModule.getInstance().latestFileURL+" ,time="+player.formattedTime+" ,streamQuality="
				+player.streamQuality+" ,connectionSpeed="+player.connectionSpeed;
		}
		
		public function sendStateReport(...args):void
		{
			var troubleID:String;
			if (args[0] != null)
				 troubleID = args[0];
			else
				 troubleID = "";	 
				
			ComModule.getInstance().setStats("stateReport :troubleInfo="+troubleID + ", version="+Capabilities.version+", serverString="+Capabilities.serverString+
				" ,fileURL="+ComModule.getInstance().latestFileURL+" ,time="+player.formattedTime+" ,streamQuality="+player.streamQuality+
				" ,connectionSpeed="+player.connectionSpeed);
			
			trappedLastCall = "stateReport :troubleInfo="+troubleID + ", version="+Capabilities.version+", serverString="+Capabilities.serverString+
			" ,fileURL="+ComModule.getInstance().latestFileURL+" ,time="+player.formattedTime+" ,streamQuality="+player.streamQuality+
			" ,connectionSpeed="+player.connectionSpeed;
		}
		
		public function getStateReport(...args):String
		{
			var troubleID:String;
			if (args[0] != null)
				 troubleID = args[0];
			else
				 troubleID = "";	 
				
			return String("stateReport :troubleInfo="+troubleID + ", version="+Capabilities.version+", serverString="+Capabilities.serverString+
				" ,fileURL="+ComModule.getInstance().latestFileURL+" ,time="+player.formattedTime+" ,streamQuality="+player.streamQuality+
				" ,connectionSpeed="+player.connectionSpeed);

		}
		
		override protected function connError(evt:ErrorEvent=null):void {  checkTrackableEvent(ErrorEvent.CONNECTION_ERROR); }
		override protected function coreStateUpdated(evt:Event=null):void { checkTrackableEvent(evt.type);  }
		override protected function fullscreenHandler(evt:FullScreenEvent):void { checkTrackableEvent(stage.displayState); }
		override protected function sizeChanged(evt:PyroEvent=null):void{ checkTrackableEvent(PyroEvent.SIZE_UPDATE); }
		override protected function streamStatusUpdated(evt:StatusUpdateEvent):void { checkTrackableEvent(player.status);  }
		override protected function streamCompleted(evt:PyroEvent):void { checkTrackableEvent(PyroEvent.COMPLETED); }
		override protected function streamStarted(evt:PyroEvent):void 
		{ 
			resetTrackingTables();
			if (trappedLastCall != PyroEvent.STARTED)
			{
				ComModule.getInstance().setStats(PyroEvent.STARTED+" :streamURL="+ComModule.getInstance().latestFileURL);
				trappedLastCall = PyroEvent.STARTED;
			}
		}
		
		override protected function streamStopped(evt:PyroEvent):void {checkTrackableEvent(PyroEvent.STOPPED); }
		
	}
}